#include "FirstPersonCamera.h"
#include "Input.h"
#include "Time.h"
#include "render_v1.h"

using namespace hxe;

FirstPersonCamera::FirstPersonCamera(Vector3 forward, Vector3 up, float fov, float aspect, float near, float far) :
    Camera(forward, up, fov, aspect, near, far)
{
    this->mousePosition = InputInst->getMousePosition();
}

void FirstPersonCamera::goForward(float distance)
{
    gameObject->transform->position -= distance * this->gameObject->transform->forward;
}

void FirstPersonCamera::goBack(float distance)
{
    goForward(-distance);
}

void FirstPersonCamera::strafeLeft(float distance)
{
    gameObject->transform->position -= distance * this->gameObject->transform->right;;
}

void FirstPersonCamera::strafeRight(float distance)
{
    strafeLeft(-distance);
}

void FirstPersonCamera::yaw(float distance)
{
    Quaternion q = glm::normalize(glm::angleAxis(-distance, Vector3(0.0f, 1.0f, 0.0f)));
    this->gameObject->transform->forward = glm::normalize(q * this->gameObject->transform->forward);
    this->gameObject->transform->right = glm::normalize(q * this->gameObject->transform->right);
    this->gameObject->transform->up = glm::normalize(q * this->gameObject->transform->up);
}

void FirstPersonCamera::pitch(float distance)
{
    Vector3 right = this->gameObject->transform->right;
    Quaternion q = glm::normalize(glm::angleAxis(distance, right));
    this->gameObject->transform->forward = glm::normalize(q * this->gameObject->transform->forward);
    this->gameObject->transform->up = glm::normalize(glm::cross(this->gameObject->transform->forward, this->gameObject->transform->right));
}

void FirstPersonCamera::update()
{
    float distance = Engine::getInstance()->getTime()->getDeltaTime() * 10.0f;
    Input* input = InputInst;

    if (input->getKeyDown(GLFW_KEY_LEFT_SHIFT))
    {
        distance *= 5.0f;
    }

    if (input->getKeyDown(GLFW_KEY_W))
    {
        goForward(distance);
    }

    if (input->getKeyDown(GLFW_KEY_S))
    {
        goBack(distance);
    }

    if (input->getKeyDown(GLFW_KEY_A))
    {
        strafeLeft(distance);
    }

    if (input->getKeyDown(GLFW_KEY_D))
    {
        strafeRight(distance);
    }

    Vector2 mPos = InputInst->getMousePosition();
    float xOffset = mPos.x - mousePosition.x;
    float yOffset = mousePosition.y - mPos.y;
    mousePosition = mPos;

    float sensitivity = 0.0005f;
    xOffset *= sensitivity;
    yOffset *= sensitivity;

    yaw(xOffset);
    pitch(yOffset);
}
